package com.warrior.gatherclient.service.impl;

import com.warrior.gatherclient.grpc.Messages;
import com.warrior.gatherclient.util.CommonUtil;
import com.warrior.gatherclient.service.CentralProcessorService;
import com.warrior.gatherclient.service.SystemInfoService;
import com.warrior.gathercommon.constants.CommonStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;

import java.text.DecimalFormat;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName CentralProcessorServiceImp.java
 * @Author xujian
 * @Description
 * @CreateTime 2020年12月16日 14:23:00
 */
@Slf4j
@Service
public class CentralProcessorServiceImp implements CentralProcessorService {

    @Autowired
    private SystemInfoService systemInfoService;

    @Override
    public String getServiceKey() {
        return CommonStatus.CONSTANT_CENTRAL_PROCESSOR;
    }

    @Override
    public Messages.Builder execute() {
        Messages.Builder messages = CommonUtil.initMessage(CommonStatus.CONSTANT_CENTRAL_PROCESSOR);
        SystemInfo systemInfo = systemInfoService.getSystemInfo();
        CentralProcessor processor = systemInfo.getHardware().getProcessor();
        //CPU型号
        String name = processor.getProcessorIdentifier().getName();

        Messages.Metric.Builder builder = Messages.Metric.newBuilder();
        builder.setMetricName(CommonStatus.CONSTANT_CENTRAL_PROCESSOR_INFO);
        builder.setMetricVaule(name);
        messages.addMetrics(builder);
        addCpuUsage(systemInfo, messages);
        return messages;
    }

    private void addCpuUsage(SystemInfo systemInfo, Messages.Builder messages) {
        try {
            CentralProcessor processor = systemInfo.getHardware().getProcessor();
            long[] systemCpuLoadTicks = processor.getSystemCpuLoadTicks();
            long[] prevTicks = processor.getSystemCpuLoadTicks();
            // 睡眠1s
            TimeUnit.SECONDS.sleep(1);
            long[] ticks = processor.getSystemCpuLoadTicks();
            long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
            long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
            long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
            long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
            long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
            long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
            long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
            long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
            long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
            DecimalFormat decimalFormat = new DecimalFormat(CommonStatus.CONSTANT_DECIMAL_FORMAT);

            //cpu核心数
            Messages.Metric.Builder numbuilder = Messages.Metric.newBuilder();
            numbuilder.setMetricName(CommonStatus.CONSTANT_CENTRAL_PROCESSOR_NUM);
            numbuilder.setMetricVaule(String.valueOf(processor.getLogicalProcessorCount()));
            messages.addMetrics(numbuilder);

            //系统使用情况
            Messages.Metric.Builder sysUsebuilder = Messages.Metric.newBuilder();
            sysUsebuilder.setMetricName(CommonStatus.CONSTANT_CENTRAL_PROCESSOR_SYSTEM_USE);
            String sysUse = decimalFormat.format(cSys * 1.0 / totalCpu);
            sysUsebuilder.setMetricVaule(sysUse);
            messages.addMetrics(sysUsebuilder);

            //用户使用
            Messages.Metric.Builder userUsebuilder = Messages.Metric.newBuilder();
            userUsebuilder.setMetricName(CommonStatus.CONSTANT_CENTRAL_PROCESSOR_USER_USE);
            String userUse = decimalFormat.format(user * 1.0 / totalCpu);
            userUsebuilder.setMetricVaule(userUse);
            messages.addMetrics(userUsebuilder);

            //总共使用
            Messages.Metric.Builder allUsebuilder = Messages.Metric.newBuilder();
            allUsebuilder.setMetricName(CommonStatus.CONSTANT_CENTRAL_PROCESSOR_ALL_USE);
            String allUse = decimalFormat.format(1.0 - (idle * 1.0 / totalCpu));
            allUsebuilder.setMetricVaule(allUse);
            messages.addMetrics(allUsebuilder);

            //io延时
            Messages.Metric.Builder ioWaitbuilder = Messages.Metric.newBuilder();
            ioWaitbuilder.setMetricName(CommonStatus.CONSTANT_CENTRAL_PROCESSOR_IO_WAIT);
            String ioWait = decimalFormat.format(iowait * 1.0 / totalCpu);
            ioWaitbuilder.setMetricVaule(ioWait);
            messages.addMetrics(ioWaitbuilder);
        } catch (Exception e) {
            log.error("============== 采集cpu信息异常 msg: {} =============", e.getMessage());
        }
    }

}
